/*extern crate sync;

use sync::DuplexStream;

#[deriving(Clone)]
struct StructPerson {
    name: ~str,
    age: f64
}

enum PersonMessage {
    Person(StructPerson),
    Finished
}

fn main() {
    let mut sp = StructPerson { name: ~"Struct Person", age: 10f64 };
    let mut sp_dup = sp.clone();
    println!("Struct Person 1: {}, {}", sp.name, sp.age);
    println!("Struct Person 2: {}, {}", sp_dup.name, sp_dup.age);

    sp.name = ~"Changed Name";
    sp.age = 100f64;

    sp_dup.name = ~"Changed Dup Name";
    sp_dup.age = 200f64;

    println!("Struct Person 1: {}, {}", sp.name, sp.age);
    println!("Struct Person 2: {}, {}", sp_dup.name, sp_dup.age);

    let (people, child) = sync::duplex();
    spawn(proc() { adder(&child); });
    for _ in range(0, 10000) {
        // I'm just cloning here for simplicity, since sp is 'moved' 
        // if you don't want to do a clone, you could use an arc
        people.send(Person(sp.clone())); 
    }
    people.send(Finished);
    let total = people.recv();
    println!("Sum: {}", total);
}

fn adder(people: &DuplexStream<f64, PersonMessage>) {
    let mut sum = 0f64;
    loop {
        let message: PersonMessage = people.recv();
        let finished = match message {
            Person(p) => {
                sum += p.age;
                false
            },
            Finished  => {
                people.send(sum);
                true
            }
        };
        if finished { break;}
    }
}*/
extern crate sync;
extern crate green;
extern crate rustuv;
extern crate rand;

use sync::{Arc, Mutex};
use std::task::TaskOpts;
use std::io::timer::sleep;
use green::{SchedPool, PoolConfig};

#[deriving(Clone)]
struct Person {
    //For the purposes of this demonstration, you could use &str here. But in
    //general that would mean you would need to ensure the name string lasts
    //longer than the Person structure.
    name: ~str,
    age: f64,
}

fn main() {
    {
        let mut sP = Person{name: ~"Struct 1", age: 10.0};
        let mut sP_dup = sP.clone();
        println!("StructPerson 1: {} , {}", sP.name, sP.age);
        println!("StructPerson 2: {} , {}", sP_dup.name, sP_dup.age);

        sP.name = ~"Changed Name";
        sP.age = 100.0;

        sP_dup.name = ~"Changed Dup Name";
        sP_dup.age = 100.0;

        println!("StructPerson 1: {} , {}", sP.name, sP.age);
        println!("StructPerson 2: {} , {}", sP_dup.name, sP_dup.age);
    }
    println!("==============================")
    {
        //Rust doesn't allow two mutable views of the same data without locking,
        //so this is more complicated than the C# version. In practise you
        //wouldn't do this.
        let sP = Arc::new(Mutex::new(Person{name: ~"Struct 1", age: 10.0}));
        let sP_dup = sP.clone();
        {
            let sP = sP.lock();
            println!("StructPerson 1: {} , {}", (*sP).name, (*sP).age);
        }
        {
            let sP = sP_dup.lock();
            println!("StructPerson 2: {} , {}", (*sP).name, (*sP).age);
        }
        {
            let mut sP = sP.lock();
            (*sP).name = ~"Changed Name";
            (*sP).age = 100.0;
        }
        {
            let mut sP = sP_dup.lock();
            (*sP).name = ~"Changed Dup Name";
            (*sP).age = 200.0;
        }
        {
            let sP = sP.lock();
            println!("StructPerson 1: {} , {}", (*sP).name, (*sP).age);
        }
        {
            let sP = sP_dup.lock();
            println!("StructPerson 2: {} , {}", (*sP).name, (*sP).age);
        }

        println!("==============================")
        (*sP.lock()).age = 1.0;
        //Also create a lock around the sum counter. This is the same as the C#
        //code except the lock is separate.
        let sum = Arc::new(Mutex::new(0.0f64));

        let mut pool_cfg = PoolConfig::new();
        //Need to do this for sleep() to work in the spawned tasks.
        //Otherwise the basic event loop is OK.
        pool_cfg.event_loop_factory = rustuv::event_loop;
        let mut pool = SchedPool::new(pool_cfg);

        for _ in range(0, 10_000) {
            //create clones of the MutexArcs before moving them into the new
            //task
            let sum = sum.clone();
            let sP = sP.clone();
            pool.spawn(TaskOpts::new(), proc() {
                let mut sum = sum.lock();
                let sP = sP.lock();
                *sum += (*sP).age;
                let ms = (rand::random::<f32>()).round() as u64;
                sleep(ms);
            });
        }

        pool.shutdown();

        println!("Sum = {}", *sum.lock());

        //last Arc reference is dropped here, so the memory is freed.
        //This doesn't use GC so reference cycles will leak memory 
        //but that isn't an issue in this case.
    }
}

/*
    //1000000000.0 nano second
    //println!("{:s}",time::strftime("%Y-%m-%dT%H:%M:%SZ",&ti));

    //let mut read_result;
    let mut strResponse: ~str;
    
    socket.write(bytes!("GET / HTTP/1.0\r\n\r\n"));
    let mut response = socket.read_to_str();

    println!("{:s}Request:{:d}",response.unwrap(),n);
    
    //let mut socket; //= TcpStream::connect(addr).unwrap();
    
    for _ in range(0,200)
    {
        //println!("{:?}",ti);

        let mut socket=TcpStream::connect(addr).unwrap();
        match socket.write(req.as_bytes())
        {
            Ok(_) =>  match socket.read_to_end() 
            {
                Ok(_) => 
                {           //
                            GET+=1;
                            //println!("S:{:.1s} Req {:d}", response, n)
                },
                Err(e)  => println!("ERROR: {:?}", e)
            },
            
            Err(e) => println!("ERROR: {:?}",e)
        }
        drop(socket);
    }


    for _ in range(0,200)
    {
        

        let mut socket = TcpStream::connect(addr).unwrap();

        socket.write(req.as_bytes());
        strResponse = socket.read_to_str().unwrap();
        //println!("{:.10s}Request:{:d}",strResponse,n);
        drop(socket);
        n+=1;
        socket = TcpStream::connect(addr).unwrap();
        socket.write(bytes!("put / HTTP/1.0\r\n\r\n"));
        strResponse = socket.read_to_str().unwrap();
        //println!("{:.10s}Request:{:d}",strResponse,n);
        drop(socket);
        n+=1;
    }
      let ti = time::now();
  let time_now = time::get_time();
        //let args: ~[~str] = ::std::os::args();
  //println!("{}",args[1]); 
    //println!("{:?}",time::strftime("{:d}",&ti));
    let t2 = time::now();
    let time_dif_min = t2.tm_min - ti.tm_min;
    let time_dif_sec = t2.tm_sec - ti.tm_sec;
    let time_dif_nsec = t2.tm_nsec -ti.tm_nsec;
    let time_then = time::get_time();

    println!("Time Now: {:d}",time_now.nsec);
    println!("Time Then: {:d}",time_then.nsec);
    println!("{:d} Requests to {:s} Min:{:d} Sec:{:d} Nsec:{:d} ",n,addr.to_str(),time_dif_min,time_dif_sec,time_dif_nsec);

        let addr = from_str::<SocketAddr>("127.0.0.1:8080").unwrap();
    let ad : ~str = ~"127.0.0.1:8080";
*/
    /*n = 0;
    println!("Second set of requests");
    for n in range(0,20)
    {
        socket.write(bytes!("GET / HTTP/1.0\n\n"));
        response = socket.read_to_end();
        println!("{}{:d}",response,n);
    }*/
    //let mut response = socket.read_to_str().unwrap();
    //let addr = SocketAddr { ip: Ipv4Addr(127, 0, 0, 1), port: 8080 };
    //let mut stream = TcpStream::connect(addr);
    
    //println!("{:s}",response.unwrap());
    /*match drop(socket)
    
    {
        Ok() => println!("Done"),
        Err(e) => println!("{:?}",e)
    }*/
  //let mut reader = BufferedReader::new(io::stdin());
  //let input = reader.read_line().unwrap();
  //println("YOU TYPED:");
  //println(input);
    
    /*stream.write([1]);
    let mut buf = [0];
    stream.read(buf);
    drop(stream); // close the connection
*/ 